#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <signal.h>

//int msgget(key_t key, int msgflg);
//key_t ftok(const char *pathname, int proj_id);
//int msgctl(int msqid, int cmd, struct msqid_ds *buf);
//int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
//ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

struct msgbuf {
    long mtype;         /* message type, must be > 0 */
    char mtext[1024];    /* message data */
};

int main(int argc, char *argv){
    int ret = 0;
    int len;
    pid_t pid;
    key_t key = ftok("./msgget.txt", 'a');
    if(key < 0){
        perror("ftok() error:");
        exit(-1);
    }

    //创建消息队列
    int msgid = msgget(key, IPC_CREAT | 0777);
    if(msgid < 0){
       perror("msgget() error:");
       exit(-1);
    }
    system("ipcs -q");

    pid = fork();
    if(pid < 0){
        perror("fork() error!");
        exit(-1);
    }

    if(pid > 0){
        struct msgbuf sendMsg;
        sendMsg.mtype = 100;
        while(1){
            memset(sendMsg.mtext, 0, sizeof(sendMsg.mtext));
            fgets(sendMsg.mtext, sizeof(sendMsg.mtext), stdin);
            len = strlen(sendMsg.mtext);
            if (len > 0 && sendMsg.mtext[len - 1] == '\n') {
                sendMsg.mtext[len - 1] = '\0';  // 替换换行符
            }
            //msgflg:IPC_NOWAIT 非阻塞,0是阻塞
            ret = msgsnd(msgid, (const void *)&sendMsg, sizeof(sendMsg.mtext), 0);
            if(ret < 0){
                perror("msgsnd() error:");
                exit(-1);
            }
            if(!strncmp(sendMsg.mtext, "exit", 4)){
                 break;
            }
        }
        
        //等待子进程退出
        wait(NULL);
        //删除消息队列
        ret = msgctl(msgid, IPC_RMID, NULL);
        if(ret < 0){
            perror("msgctl() error:");
            exit(-1);
        }
        system("ipcs -q");
    }else{
        struct msgbuf recvMsg;
        recvMsg.mtype = 200; //200是消息类型
        while(1){
            memset(recvMsg.mtext, 0, sizeof(recvMsg.mtext));
            ssize_t count = msgrcv(msgid, (void *)&recvMsg, sizeof(recvMsg.mtext), 200, 0);
            if(count < 0){
                perror("msgrcv() error:");
                exit(-1);
            }        
            printf("recv:msg = [%s]\n", recvMsg.mtext);
            if(!strncmp(recvMsg.mtext, "exit", 4)){
                 break;
            }
        }
    }
    return 0;
}
